﻿/**
 * @file std_bitset.c
 * Copyright (c) 2024 Gaaagaa. All rights reserved.
 * 
 * @author  : Gaaagaa
 * @date    : 2024-08-28
 * @version : 1.0.0.0
 * @brief   : 使用 C API 的接口形式实现 位集（位图） 操作类。
 */

/**
 * The MIT License (MIT)
 * Copyright (c) Gaaagaa. All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "std_bitset.h"
#include "std_debug.h"
#include "std_bitset.inl"

////////////////////////////////////////////////////////////////////////////////

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif // __GNUC__

////////////////////////////////////////////////////////////////////////////////

//====================================================================

// 
// xstd_bitset_t 的内部相关操作接口
// 

/**********************************************************/
/**
 * @brief 按 字 宽度，对 位标识状态 进行测试。
 * 
 * @param [in ] xbs_this : xstd_bitset_t 对象。
 * @param [in ] xst_bpos : 测试区间的 起始字索引号。
 * @param [in ] xst_epos : 测试区间的 结束字索引号。
 * @param [in ] xbs_mark : 测试的标识状态。
 * 
 * @return xbs_ipos_t : 遍历区间后，位索引 最终 指向的位置。
 */
static xbs_ipos_t bitset_test_words(
                    xbs_this_t xbs_this,
                    xbs_size_t xst_bpos,
                    xbs_size_t xst_epos,
                    xbs_mark_t xbs_mark)
{
    xbs_size_t xst_wpos = xst_bpos;

    if (xbs_mark)
    {
        for (; xst_wpos < xst_epos; ++xst_wpos)
        {
            if (XBS_WORD_MARKED != xbs_this->xbs_bits[xst_wpos])
                break;
        }
    }
    else
    {
        for (; xst_wpos < xst_epos; ++xst_wpos)
        {
            if (XBS_WORD_UNMARKED != xbs_this->xbs_bits[xst_wpos])
                break;
        }
    }

    return XBS_WPOS_IPOS(xst_wpos);
}

/**********************************************************/
/**
 * @brief 按 字 宽度，修改 整字所有位 的 位标识状态 。
 * 
 * @param [in,out] xbs_this : xstd_bitset_t 对象。
 * @param [in    ] xst_bpos : 操作区间的 起始字索引号。
 * @param [in    ] xst_epos : 操作区间的 结束字索引号。
 * @param [in    ] xbs_mark : 修改的标识状态。
 * 
 * @return xbs_ipos_t : 遍历区间后，位索引 最终 指向的位置。
 */
static xbs_ipos_t bitset_mark_words(
                    xbs_this_t xbs_this,
                    xbs_size_t xst_bpos,
                    xbs_size_t xst_epos,
                    xbs_mark_t xbs_mark)
{
    xbs_size_t xst_wpos = xst_bpos;

    if (xbs_mark)
    {
        for (; xst_wpos < xst_epos; ++xst_wpos)
        {
            if (XBS_WORD_UNMARKED != xbs_this->xbs_bits[xst_wpos])
                break;

            xbs_this->xbs_bits[xst_wpos] = XBS_WORD_MARKED;
            XBS_BITS_NSET(xbs_this) += XBS_WORD_WIDE;
        }
    }
    else
    {
        for (; xst_wpos < xst_epos; ++xst_wpos)
        {
            if (XBS_WORD_MARKED != xbs_this->xbs_bits[xst_wpos])
                break;

            xbs_this->xbs_bits[xst_wpos] = XBS_WORD_UNMARKED;
            XBS_BITS_NSET(xbs_this) -= XBS_WORD_WIDE;
        }
    }

    return XBS_WPOS_IPOS(xst_wpos);
}

/**********************************************************/
/**
 * @brief 统计整字中，位状态 为 已标识 的位数量。
 */
static inline xbs_size_t bitset_mbits(xbs_word_t xbs_word)
{
    xbs_size_t xst_count = 0;

    while ((xbs_word_t)0 != xbs_word)
    {
        xst_count += (xbs_size_t)(xbs_word & (xbs_word_t)1);
        xbs_word >>= 1;
    }

    return xst_count;
}

/**********************************************************/
/**
 * @brief 反转 整字区间 [ xst_bpos, xst_epos ) 所有位 的 标识状态。
 * 
 * @param [in,out] xbs_this : xstd_bitset_t 对象。
 * @param [in    ] xst_bpos : 整字区间的 起始索引号。
 * @param [in    ] xst_epos : 整字区间的 结束索引号。
 * 
 * @return xbs_ipos_t : 遍历区间后，位索引 最终 指向的位置。
 */
static xbs_ipos_t bitset_flip_words(
                        xbs_this_t xbs_this,
                        xbs_size_t xst_bpos,
                        xbs_size_t xst_epos)
{
    xbs_size_t xst_bits;
    xbs_size_t xst_wpos = xst_bpos;

    for (; xst_wpos < xst_epos; ++xst_wpos)
    {
        xst_bits = bitset_mbits(xbs_this->xbs_bits[xst_wpos]);

        xbs_this->xbs_bits[xst_wpos] = ~xbs_this->xbs_bits[xst_wpos];
        XBS_BITS_NSET(xbs_this) += (XBS_WORD_WIDE - (xst_bits << 1));
    }

    return XBS_WPOS_IPOS(xst_wpos);
}

//====================================================================

// 
// xstd_bitset_t 的外部相关操作接口
// 

/**********************************************************/
/**
 * @brief 返回内部的 sizeof(xstd_bitset_t) 值。
 */
xbs_size_t std_bitset_sizeof(void)
{
    return (xbs_size_t)sizeof(xstd_bitset_t);
}

/**********************************************************/
/**
 * @brief 创建 xstd_bitset_t 对象。
 * @note 
 * 1. 入参 xbs_ctxt 中的 内存管理对象，若其中的某个回调函数
 *    为 XBS_NULL，则配置成全局管理对象对应函数接口。
 * 2. 可使用 @see std_bitset_destroy() 销毁对象。
 * 3. 忽略 xbs_ctxt 中的 xstd_etype、xstd_esize 两个字段的设定值。
 * 
 * @param [in ] xbs_ctxt : 所存储位的类型上下文描述信息（若为 XBS_NULL，则取内部默认值）。
 * @param [in ] xst_size : 位数量。
 * 
 * @return xbs_this_t : xstd_bitset_t 对象句柄。
 */
xbs_this_t std_bitset_create(xbs_ctxt_t xbs_ctxt, xbs_size_t xst_size)
{
    xbs_this_t xbs_this;

    if (XBS_NULL == xbs_ctxt)
        xbs_this = xstd_altor_comm.xfunc_allocate(sizeof(xstd_bitset_t));
    else
        xbs_this = xbs_ctxt->xstd_altor->xfunc_allocate(sizeof(xstd_bitset_t));
    XASSERT(XBS_NULL != xbs_this);

    return std_bitset_emplace_create(xbs_this, xbs_ctxt, xst_size);
}

/**********************************************************/
/**
 * @brief 销毁 xstd_bitset_t 对象，其由 @see std_bitset_create() 创建。
 */
xbs_void_t std_bitset_destroy(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);

    xstd_altor_t xstd_altor = XBS_ALTOR(xbs_this);

    std_bitset_emplace_destroy(xbs_this);
    xstd_altor->xfunc_dealloc(xbs_this);
}

/**********************************************************/
/**
 * @brief 创建 xstd_bitset_t 对象。
 * @note 
 * 1. 入参 xbs_ctxt 中的 内存管理对象，若其中的某个回调函数
 *    为 XBS_NULL，则配置成全局管理对象对应函数接口。
 * 2. 可使用 @see std_bitset_emplace_destroy() 销毁对象。
 * 3. 忽略 xbs_ctxt 中的 xstd_etype、xstd_esize 两个字段的设定值。
 * 
 * @param [in,out] xbs_this : 
 * 存储 xstd_bitset_t 对象的缓存，
 * 其大小不可小于 std_bitset_sizeof() 的返回值。
 * 
 * @param [in    ] xbs_ctxt : 所存储位的类型上下文描述信息（若为 XBS_NULL，则取内部默认值）。
 * @param [in    ] xst_size : 位数量。
 * 
 * @return xbs_this_t : xstd_bitset_t 对象句柄。
 */
xbs_this_t std_bitset_emplace_create(
                xbs_this_t xbs_this,
                xbs_ctxt_t xbs_ctxt,
                xbs_size_t xst_size)
{
    XASSERT(XBS_NULL != xbs_this);

    //======================================

    xbs_this->xstd_ectxt.xstd_etype = 0;
    xbs_this->xstd_ectxt.xstd_esize = 0;
    xbs_this->xstd_ectxt.xstd_owner = xbs_this;

    if (XBS_NULL == xbs_ctxt)
    {
        xbs_this->xstd_ectxt.xstd_altor = (xstd_altor_t)&xstd_altor_comm;
    }
    else
    {
        xbs_this->xstd_ectxt.xstd_altor = xbs_ctxt->xstd_altor;
    }

    //======================================

#define X_ALIGN(xsize) (((xsize) + XBS_WORD_WIDE - 1) & ~(XBS_WORD_WIDE - 1))
#define X_NBYTE(xsize) (X_ALIGN(xsize) >> 3)

    XBS_BITS_SIZE(xbs_this) = X_ALIGN(xst_size);
    XBS_BITS_NSET(xbs_this) = 0;

    xbs_this->xbs_bits = XBS_MALLOC(xbs_this, X_NBYTE(xst_size));
    XASSERT(XBS_NULL != xbs_this->xbs_bits);

    std_bitset_reset(xbs_this);

#undef X_ALIGN
#undef X_NBYTE

    //======================================

    return xbs_this;
}

/**********************************************************/
/**
 * @brief 在指定缓存上销毁 xstd_bitset_t 对象。
 * @note  xstd_bitset_t 对象是由 @see std_bitset_emplace_create() 创建。
 */
xbs_void_t std_bitset_emplace_destroy(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);

    XBS_DEALLOC(xbs_this, xbs_this->xbs_bits);

    XBS_BITS_SIZE(xbs_this) = 0;
    XBS_BITS_NSET(xbs_this) = 0;
    xbs_this->xbs_bits      = XBS_NULL;
}

/**********************************************************/
/**
 * @brief 判断 xstd_bitset_t 对象是否有 已标识状态 的位。
 */
xbs_bool_t std_bitset_any(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);
    return (0 != XBS_BITS_NSET(xbs_this));
}

/**********************************************************/
/**
 * @brief 判断 xstd_bitset_t 对象的 所有位 是否都是 未标识状态。
 */
xbs_bool_t std_bitset_none(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);
    return (0 == XBS_BITS_NSET(xbs_this));
}

/**********************************************************/
/**
 * @brief 判断 xstd_bitset_t 对象的 所有位 是否都是 已标识状态。
 */
xbs_bool_t std_bitset_all(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);
    return (XBS_BITS_SIZE(xbs_this) == XBS_BITS_NSET(xbs_this));
}

/**********************************************************/
/**
 * @brief 统计 xstd_bitset_t 对象 已标识位 的数量。
 */
xbs_size_t std_bitset_count(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);
    return XBS_BITS_NSET(xbs_this);
}

/**********************************************************/
/**
 * @brief 返回 xstd_bitset_t 对象的 位容量。
 */
xbs_size_t std_bitset_size(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);
    return XBS_BITS_SIZE(xbs_this);
}

/**********************************************************/
/**
 * @brief 获取 xstd_bitset_t 对象指定位的 位标识状态。
 * 
 * @param [in ] xbs_this : xstd_bitset_t 对象。
 * @param [in ] xbs_ipos : 指定位的 位索引。
 * 
 * @return xbs_mark_t : 标识状态值。可参看 @see xbs_mark_t 相关枚举值。
 */
xbs_mark_t std_bitset_at(xbs_this_t xbs_this, xbs_ipos_t xbs_ipos)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ipos < XBS_IPOS_END(xbs_this));
    return XBS_ISMARK(xbs_this, xbs_ipos);
}

/**********************************************************/
/**
 * @brief 重置 xstd_bitset_t 对象的所有位 为 未标识状态。
 */
xbs_void_t std_bitset_reset(xbs_this_t xbs_this)
{
    XASSERT(XBS_NULL != xbs_this);

    xbs_size_t xst_wpos = 0;
    xbs_size_t xst_epos = XBS_IPOS_WPOS(XBS_IPOS_END(xbs_this));
    for (; xst_wpos < xst_epos; ++xst_wpos)
    {
        xbs_this->xbs_bits[xst_wpos] = XBS_WORD_UNMARKED;
    }

    XBS_BITS_NSET(xbs_this) = 0;
}

/**********************************************************/
/**
 * @brief 测试 xstd_bitset_t 对象中 指定位 的 标识状态。
 * 
 * @param [in ] xbs_this : xstd_bitset_t 对象。
 * @param [in ] xbs_ipos : 测试位的 位索引。
 * @param [in ] xbs_mark : 测试的 标识状态。
 * 
 * @return xbs_bool_t : 测试位 的标识状态，是否与 测试状态 一致。
 */
xbs_bool_t std_bitset_testi(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ipos,
                xbs_mark_t xbs_mark)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ipos < XBS_IPOS_END(xbs_this));
    XASSERT((XBS_UNMARKED == xbs_mark) || (XBS_MARKED == xbs_mark));
    return (XBS_ISMARK(xbs_this, xbs_ipos) == xbs_mark);
}

/**********************************************************/
/**
 * @brief 测试 xstd_bitset_t 对象 区间 [ xbs_ibgn, xbs_iend ) 的 位标识状态。
 * 
 * @param [in ] xbs_this : xstd_bitset_t 对象。
 * @param [in ] xbs_ibgn : 测试区间 的 起始位索引。
 * @param [in ] xbs_iend : 测试区间 的 结束位索引。
 * @param [in ] xbs_mark : 测试的 标识状态。
 * 
 * @return xbs_size_t : 
 * 返回 通过测试 的 位数量，其意义可理解为
 * 区间 [ xbs_ibgn, xbs_ibgn + 返回值 ) 的 位状态 均为 xbs_mark 。
 * 当然 返回值 为 0 时，表示 没有任何一位 通过测试。
 */
xbs_size_t std_bitset_testn(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ibgn,
                xbs_ipos_t xbs_iend,
                xbs_mark_t xbs_mark)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ibgn <= xbs_iend);
    XASSERT(xbs_ibgn <= XBS_IPOS_END(xbs_this));
    XASSERT((XBS_UNMARKED == xbs_mark) || (XBS_MARKED == xbs_mark));

    xbs_ipos_t xbs_ipos = xbs_ibgn;
    xbs_ipos_t xbs_iewd;

    //======================================
    // 测试区间为 [ xbs_ibgn, xbs_iend )

    if (xbs_iend > XBS_IPOS_END(xbs_this))
    {
        xbs_iend = XBS_IPOS_END(xbs_this);
    }

    // 若区间 [ xbs_ibgn, xbs_iend ) 未跨越 一个整字，
    // 则只须对 区间 的 非整字尾部 进行遍历
    if (XBS_IPOS_WBEGIN(xbs_ibgn) == XBS_IPOS_WBEGIN(xbs_iend))
    {
        goto __BITS_IEND;
    }

    // 若 区间起始位 刚好 对齐到 整字，则按 整字 进行遍历
    if (xbs_ibgn == XBS_IPOS_WBEGIN(xbs_ibgn))
    {
        goto __BITS_WORD;
    }

    //======================================
    // 对区间 的 非整字首部 进行遍历

    xbs_iewd = XBS_IPOS_WBEGIN(xbs_ibgn) + XBS_WORD_WIDE;
    for (; xbs_ipos < xbs_iewd; ++xbs_ipos)
    {
        if (XBS_ISMARK(xbs_this, xbs_ipos) != xbs_mark)
            goto __EXIT;
    }

    //======================================
    // 对区间 的 整字中部 进行遍历

__BITS_WORD:

    XASSERT(xbs_ipos == XBS_IPOS_WBEGIN(xbs_ipos));

    if (xbs_ipos < XBS_IPOS_WBEGIN(xbs_iend))
    {
        xbs_ipos = bitset_test_words(
                            xbs_this,
                            XBS_IPOS_WPOS(xbs_ipos),
                            XBS_IPOS_WPOS(xbs_iend),
                            xbs_mark);
    }

    //======================================
    // 对区间 的 非整字尾部 进行遍历

__BITS_IEND:

    for (; xbs_ipos < xbs_iend; ++xbs_ipos)
    {
        if (XBS_ISMARK(xbs_this, xbs_ipos) != xbs_mark)
            goto __EXIT;
    }

    //======================================

__EXIT:

    return (xbs_size_t)(xbs_ipos - xbs_ibgn);
}

/**********************************************************/
/**
 * @brief 设置 xstd_bitset_t 对象的 位标识状态。
 * @note  要求所设置位，其当前 标识状态 与 设置的状态 相反。
 * 
 * @param [in,out] xbs_this : xstd_bitset_t 对象。
 * @param [in    ] xbs_ipos : 操作位 的 位索引。
 * @param [in    ] xbs_mark : 设置的 标识状态。
 * 
 * @return xbs_bool_t : 操作是否成功。
 */
xbs_bool_t std_bitset_marki(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ipos,
                xbs_mark_t xbs_mark)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ipos < XBS_IPOS_END(xbs_this));
    XASSERT((XBS_UNMARKED == xbs_mark) || (XBS_MARKED == xbs_mark));

    if (XBS_ISMARK(xbs_this, xbs_ipos) == xbs_mark)
        return XBS_FALSE;

    if (xbs_mark)
        XBS_MARK(xbs_this, xbs_ipos);
    else
        XBS_UNMARK(xbs_this, xbs_ipos);

    return XBS_TRUE;
}

/**********************************************************/
/**
 * @brief 设置 xstd_bitset_t 对象区间 [ xbs_ibgn, xbs_iend ) 的 位标识状态。
 * @note  要求所设置的所有位，其当前 标识状态 与 设置的状态 相反。
 * 
 * @param [in,out] xbs_this : xstd_bitset_t 对象。
 * @param [in    ] xbs_ibgn : 操作区间 的 起始位索引。
 * @param [in    ] xbs_iend : 操作区间 的 结束位索引。
 * @param [in    ] xbs_mark : 设置的 标识状态。
 * 
 * @return xbs_bool_t : 操作是否成功。
 */
xbs_bool_t std_bitset_markn(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ibgn,
                xbs_ipos_t xbs_iend,
                xbs_mark_t xbs_mark)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ibgn <= xbs_iend);
    XASSERT(xbs_iend <= XBS_IPOS_END(xbs_this));
    XASSERT((XBS_UNMARKED == xbs_mark) || (XBS_MARKED == xbs_mark));

    xbs_ipos_t xbs_ipos = xbs_ibgn;
    xbs_ipos_t xbs_iewd;

    //======================================
    // 设置操作区间为 [ xbs_ibgn, xbs_iend )

    // 若区间 [ xbs_ibgn, xbs_iend ) 未跨越 一个整字，
    // 则只须对 区间 的 非整字尾部 进行遍历
    if (XBS_IPOS_WBEGIN(xbs_ibgn) == XBS_IPOS_WBEGIN(xbs_iend))
    {
        goto __BITS_IEND;
    }

    // 若 区间起始位 刚好 对齐到 整字，则按 整字 进行遍历
    if (xbs_ibgn == XBS_IPOS_WBEGIN(xbs_ibgn))
    {
        goto __BITS_WORD;
    }

    //======================================
    // 对区间 的 非整字首部 进行遍历

    xbs_iewd = XBS_IPOS_WBEGIN(xbs_ibgn) + XBS_WORD_WIDE;
    for (; xbs_ipos < xbs_iewd; ++xbs_ipos)
    {
        if (XBS_ISMARK(xbs_this, xbs_ipos) == xbs_mark)
        {
            std_bitset_markn(xbs_this, xbs_ibgn, xbs_ipos, XBS_INVERT_MARK(xbs_mark));
            return XBS_FALSE;
        }

        if (xbs_mark)
            XBS_MARK(xbs_this, xbs_ipos);
        else
            XBS_UNMARK(xbs_this, xbs_ipos);
    }

    //======================================
    // 对区间 的 整字中部 进行遍历

__BITS_WORD:

    XASSERT(xbs_ipos == XBS_IPOS_WBEGIN(xbs_ipos));

    if (xbs_ipos < XBS_IPOS_WBEGIN(xbs_iend))
    {
        xbs_ipos = bitset_mark_words(
                            xbs_this,
                            XBS_IPOS_WPOS(xbs_ipos),
                            XBS_IPOS_WPOS(xbs_iend),
                            xbs_mark);
        if (xbs_ipos != XBS_IPOS_WBEGIN(xbs_iend))
        {
            std_bitset_markn(xbs_this, xbs_ibgn, xbs_ipos, XBS_INVERT_MARK(xbs_mark));
            return XBS_FALSE;
        }
    }

    //======================================
    // 对区间 的 非整字尾部 进行遍历

__BITS_IEND:

    for (; xbs_ipos < xbs_iend; ++xbs_ipos)
    {
        if (XBS_ISMARK(xbs_this, xbs_ipos) == xbs_mark)
        {
            std_bitset_markn(xbs_this, xbs_ibgn, xbs_ipos, XBS_INVERT_MARK(xbs_mark));
            return XBS_FALSE;
        }

        if (xbs_mark)
            XBS_MARK(xbs_this, xbs_ipos);
        else
            XBS_UNMARK(xbs_this, xbs_ipos);
    }

    //======================================

    return XBS_TRUE;
}

/**********************************************************/
/**
 * @brief 对 xstd_bitset_t 对象指定位 进行 标识状态 反转。
 * 
 * @param [in,out] xbs_this : xstd_bitset_t 对象。
 * @param [in    ] xbs_ipos : 操作位 的 位索引。
 */
xbs_void_t std_bitset_flipi(
            xbs_this_t xbs_this,
            xbs_ipos_t xbs_ipos)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ipos < XBS_IPOS_END(xbs_this));

    XBS_FLIPI(xbs_this, xbs_ipos);
}

/**********************************************************/
/**
 * @brief 对 xstd_bitset_t 对象区间 [ xbs_ibgn, xbs_iend ) 进行 标识状态 反转。
 * 
 * @param [in,out] xbs_this : xstd_bitset_t 对象。
 * @param [in    ] xbs_ibgn : 操作区间 的 起始位索引。
 * @param [in    ] xbs_iend : 操作区间 的 结束位索引。
 */
xbs_void_t std_bitset_flipn(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ibgn,
                xbs_ipos_t xbs_iend)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ibgn <= xbs_iend);
    XASSERT(xbs_iend <= XBS_IPOS_END(xbs_this));

    xbs_ipos_t xbs_ipos = xbs_ibgn;
    xbs_ipos_t xbs_iewd;

    //======================================
    // 反转区间为 [ xbs_ibgn, xbs_iend )

    // 若区间 [ xbs_ibgn, xbs_iend ) 未跨越 一个整字，
    // 则只须对 区间 的 非整字尾部 进行遍历
    if (XBS_IPOS_WBEGIN(xbs_ibgn) == XBS_IPOS_WBEGIN(xbs_iend))
    {
        goto __BITS_IEND;
    }

    // 若 区间起始位 刚好 对齐到 整字，则按 整字 进行遍历
    if (xbs_ibgn == XBS_IPOS_WBEGIN(xbs_ibgn))
    {
        goto __BITS_WORD;
    }

    //======================================
    // 对区间 的 非整字首部 进行遍历

    xbs_iewd = XBS_IPOS_WBEGIN(xbs_ibgn) + XBS_WORD_WIDE;
    for (; xbs_ipos < xbs_iewd; ++xbs_ipos)
    {
        XBS_FLIPI(xbs_this, xbs_ipos);
    }

    //======================================
    // 对区间 的 整字中部 进行遍历

__BITS_WORD:

    XASSERT(xbs_ipos == XBS_IPOS_WBEGIN(xbs_ipos));

    if (xbs_ipos < XBS_IPOS_WBEGIN(xbs_iend))
    {
        xbs_ipos = bitset_flip_words(
                        xbs_this,
                        XBS_IPOS_WPOS(xbs_ipos),
                        XBS_IPOS_WPOS(xbs_iend));
    }

    //======================================
    // 对区间 的 非整字尾部 进行遍历

__BITS_IEND:

    for (; xbs_ipos < xbs_iend; ++xbs_ipos)
    {
        XBS_FLIPI(xbs_this, xbs_ipos);
    }

    //======================================
}

/**********************************************************/
/**
 * @brief 在 xstd_bitset_t 对象中，从 xbs_ipos 位开始查找 符合 xbs_mark 标识状态的位。
 * 
 * @param [in ] xbs_this : xstd_bitset_t 对象。
 * @param [in ] xbs_ipos : 查找操作的 起始位索引。
 * @param [in ] xbs_mark : 指定查找的 位标识状态。
 * 
 * @return xbs_ipos_t : 返回符合状态的 位索引；失败时返回 XBS_IEND 。
 */
xbs_ipos_t std_bitset_findi(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ipos,
                xbs_mark_t xbs_mark)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ipos <= XBS_IPOS_END(xbs_this));
    XASSERT((XBS_UNMARKED == xbs_mark) || (XBS_MARKED == xbs_mark));

    xbs_ipos += std_bitset_testn(
                        xbs_this,
                        xbs_ipos,
                        XBS_IPOS_END(xbs_this),
                        XBS_INVERT_MARK(xbs_mark));
    XASSERT(xbs_ipos <= XBS_IPOS_END(xbs_this));

    return ((xbs_ipos < XBS_IPOS_END(xbs_this)) ? xbs_ipos : XBS_IEND);
}

/**********************************************************/
/**
 * @brief 
 * 在 xstd_bitset_t 对象中，从 xbs_ipos 位开始查找
 * 连续 xst_nbit 个符合 xbs_mark 标识状态的位。
 * 
 * @param [in ] xbs_this : xstd_bitset_t 对象。
 * @param [in ] xbs_ipos : 查找操作的 起始位索引。
 * @param [in ] xst_nbit : 查找符合 标识状态 的 位 的数量。
 * @param [in ] xbs_mark : 指定查找的 位标识状态。
 * 
 * @return xbs_ipos_t : 
 * 返回符合状态的 起始位索引，即区间 [ 返回的位索引, 返回的位索引 + xst_nbit )
 * 符合 xbs_mark 标识状态；而返回 XBS_IEND 时，表示查找失败。
 */
xbs_ipos_t std_bitset_findn(
                xbs_this_t xbs_this,
                xbs_ipos_t xbs_ipos,
                xbs_size_t xst_nbit,
                xbs_mark_t xbs_mark)
{
    XASSERT(XBS_NULL != xbs_this);
    XASSERT(xbs_ipos <= XBS_IPOS_END(xbs_this));
    XASSERT((XBS_UNMARKED == xbs_mark) || (XBS_MARKED == xbs_mark));

    xbs_ipos_t xbs_iend;
    xbs_size_t xst_count;

    //======================================

    if ((XBS_IBEGIN + xst_nbit) > XBS_IPOS_END(xbs_this))
    {
        return XBS_IEND;
    }

    xbs_iend = XBS_IPOS_END(xbs_this) - xst_nbit;

    //======================================

    for (; xbs_ipos <= xbs_iend; )
    {
        // 首先让 迭代器 指向 首个 标识状态 为 xbs_mark 的位，
        // 注意 bitset_testn() 的 xbs_mark 参数需要反着用
        xbs_ipos += std_bitset_testn(
                            xbs_this,
                            xbs_ipos,
                            XBS_IPOS_END(xbs_this),
                            XBS_INVERT_MARK(xbs_mark));
        if (xbs_ipos > xbs_iend)
        {
            break;
        }

        // 然后再通过探测区间 [ xbs_ipos, xbs_ipos + xst_nbit )
        // 符合 xbs_mark 标识状态的 位数量
        xst_count = std_bitset_testn(
                            xbs_this,
                            xbs_ipos,
                            xbs_ipos + xst_nbit,
                            xbs_mark);

        // 若数量达到要求，则结束查找操作
        XASSERT(xst_count <= xst_nbit);
        if (xst_count == xst_nbit)
        {
            return xbs_ipos;
        }

        // 否则，让 迭代器 跳过前面的探测区间，继续下一轮查找工作
        // 注意，（xbs_ipos + xst_count）位的 标识状态，
        // 肯定不符合 xbs_mark 值，故多 +1 直接跳过该位
        xbs_ipos += xst_count + 1;
    }

    //======================================

    return XBS_IEND;
}

////////////////////////////////////////////////////////////////////////////////

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__

////////////////////////////////////////////////////////////////////////////////
